package com.atguigu.order.controller;

import com.atguigu.order.entity.Order;
import com.atguigu.order.config.AppProperties;
import com.atguigu.order.config.OrderProperties;
import com.atguigu.order.config.RateLimitProperties;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.cloud.client.loadbalancer.LoadBalancerClient;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.client.RestTemplate;

import java.math.BigDecimal;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@RestController
@RequestMapping("/order")
@RefreshScope  // 开启配置动态刷新
public class OrderController {

    @Value("${server.port:8000}")
    private String serverPort; // 注入端口号，显示当前服务运行端口

    /**
     * DiscoveryClient - 服务发现客户端
     * Spring Cloud提供的服务发现接口，用于：
     *      1. 获取所有注册的服务列表 - getServices()
     *      2. 获取指定服务的所有实例 - getInstances(serviceName)
     *      3. 获取实例的详细信息（IP、端口、健康状态等）
     *
     */
    @Autowired
    private DiscoveryClient discoveryClient;

    /**
     * LoadBalancerClient - 带负载均衡服务发现客户端
     *      1.作用：自动选择健康的服务实例
     *      2.优势：比手动选择更智能，比@LoadBalanced更灵活
     *      3.服务调用时需要获取实例信息的场景
     */
    @Autowired
    private LoadBalancerClient loadBalancerClient;

    @Autowired
    @Qualifier("loadBalancedRestTemplate")
    private RestTemplate loadBalancedRestTemplate;

    @Autowired
    @Qualifier("normalRestTemplate")
    private RestTemplate normalRestTemplate;

    /**
     * 查看所有注册的服务
     */
    @GetMapping("services")
    public List<String> getAllServices() {
        return discoveryClient.getServices();
    }

    /**
     * 查看指定服务的所有实例
     */
    @GetMapping("/instances")
    public List<ServiceInstance> getInstance(@RequestParam String serviceName) {

        // 从 Nacos 获取指定服务的所有实例
        List<ServiceInstance> instances = discoveryClient.getInstances(serviceName);

        System.out.println("服务 [" + serviceName + "] 的实例数量：" + instances.size());
        for (ServiceInstance instance : instances) {
            System.out.println("  实例信息：");
            System.out.println("    IP: " + instance.getHost());
            System.out.println("    端口: " + instance.getPort());
            System.out.println("    URI: " + instance.getUri());
            System.out.println("    健康状态: " + instance.isSecure());
        }

        return instances;
    }


    /**
     * 手动调用服务（无负载均衡）
     */
    @GetMapping("/product/{id}")
    public Map<String, Object> getProduct(@PathVariable Long id) {
        List<ServiceInstance> instances = discoveryClient.getInstances("service-product");
        if(instances == null || instances.isEmpty())
            throw new RuntimeException("没有找到可用服务");

        // 选择实例：这里选择第一个
        // TODO: 可以优化为轮询、随机等负载均衡算法
        ServiceInstance instance = instances.get(0);

        // 构造请求URL
        String url =  "http://" + instance.getHost() + ":" + instance.getPort() + "/product/" + id;

        // 发送HTTP请求（使用不带负载均衡的RestTemplate）
        Map<String, Object> response = normalRestTemplate.getForObject(url, Map.class);

        System.out.println("远程响应：" + response);

        // 构建返回结果
        Map<String, Object> result = new HashMap<>();
        result.put("调用方式", "DiscoveryClient + 手动构造URL");
        result.put("目标服务", "service-product");
        result.put("选择实例", instance.getHost() + ":" + instance.getPort());
        result.put("调用URL", url);
        result.put("商品信息", response);

        return result;
    }


    /**
     * 负载均衡调用: @LoadBalanced + 服务名调用
     * 调用流程：
     *      1. 直接使用服务名"service-product"（不写IP+端口）
     *      2. RestTemplate的拦截器自动拦截请求
     *      3. 拦截器从Nacos获取服务实例列表
     *      4. 根据负载均衡策略（如轮询）选择实例
     *      5. 将服务名替换为实际IP:Port
     *      6. 发送请求并返回响应
     */
    @GetMapping("/product2/{id}")
    public Map<String, Object> getProductWithLoadBalancer(@PathVariable Long id) {
        // 直接使用服务名构造URL
        String url = "http://service-product/product/" + id;
        System.out.println("调用URL：" + url);

        /**
         * 发送请求
         * RestTemplate会自动处理负载均衡：
         *      1. 拦截请求
         *      2. 从Nacos获取service-product实例列表
         *      3. 根据负载均衡策略选择实例
         *      4. 替换URL：service-product → 实际IP:Port
         *      5. 发送请求
         */
         Map<String, Object> response = loadBalancedRestTemplate.getForObject(url, Map.class);
         System.out.println("负载均衡后响应：" + response);

         Map<String, Object> result = new HashMap<>();
         result.put("调用方式", "@LoadBalanced + 自动负载均衡");
         result.put("目标服务", "service-product");
         result.put("调用URL（原始）", url);
         result.put("商品信息", response);

         return result;
    }

    /**
     * LoadBalancerClient服务调用:
     *      1.自动选择健康实例
     *      2.可以获取实例信息
     */
    @GetMapping("/product3/{id}")
    public Map<String, Object> getProductWithLoadBalancerClient(@PathVariable Long id) {
        // LoadBalancerClient自动选择健康的服务实例
        ServiceInstance instance = loadBalancerClient.choose("service-product");
        if(instance == null)
            throw new RuntimeException("没有可用的service-product实例");

        // 获取实例信息
        String host = instance.getHost();
        int port = instance.getPort();

        // 构造URL
        String url = "http://" + host + ":" + port + "/product/" + id;
        System.out.println("LoadBalancerClient选择了实例：" + host + ":" + port);
        System.out.println("调用URL：" + url);

        // 发送请求（使用不带负载均衡的RestTemplate）
        Map<String, Object> product = normalRestTemplate.getForObject(url, Map.class);

        // 构造返回结果
        Map<String, Object> result = new HashMap<>();
        result.put("调用方式", "LoadBalancerClient");
        result.put("选择实例", host + ":" + port);
        result.put("调用URL", url);
        result.put("商品信息", product);

        return result;
    }

    /**
     * 对比三种调用方式
     */
    @GetMapping("/compare/{id}")
    public Map<String, Object> comparedThreeMethods(@PathVariable Long id) {
        Map<String, Object> result = new HashMap<>();

        // 1.DiscoveryClient手动选择
        List<ServiceInstance> instances = discoveryClient.getInstances("service-product");
        if(!instances.isEmpty()) {
            ServiceInstance instance = instances.get(0); // 这里默认选择第一个
            String url1  = "http://" + instance.getHost() + ":" + instance.getPort() + "/product/" + id;
            result.put("方式1-DiscoveryClient", "手动选择：" + instance.getHost() + ":" + instance.getPort());
        }

        // 2.LoadBalancerClient自动选择
        ServiceInstance instance2 = loadBalancerClient.choose("service-product");
        if(instance2 != null)
            result.put("方式2-LoadBalancerClient", "自动选择：" + instance2.getHost() + ":" + instance2.getPort());

        // 3.@LoadBalanced完全自动
        result.put("方式3-@LoadBalanced", "服务名调用：http://service-product/product/" + id);

        return result;
    }

    /**
     * 创建订单接口：模拟服务间的调用
     */
    @PostMapping("/create")
    public Order createOrder(@RequestParam Long productId,
                             @RequestParam Integer quantity) {
        // 调用product服务获取商品信息
        String url = "http://service-product/product/" + productId;
        System.out.println("调用商品服务：" + url);

        Map<String, Object> product = loadBalancedRestTemplate.getForObject(url, Map.class);
        System.out.println("商品信息：" + product);

        // 创建订单
        Order order = new Order();
        order.setProductId(productId);
        order.setQuantity(quantity);
        order.setUserId(1L);
        order.setStatus("CREATED");

        // 计算总价
        if (product != null && product.containsKey("price")) {
            Object priceObj = product.get("price");
            if (priceObj != null) {
                BigDecimal price = new BigDecimal(priceObj.toString());
                BigDecimal totalPrice = price.multiply(new BigDecimal(quantity));
                order.setTotalPrice(totalPrice);
                System.out.println("订单总价：" + totalPrice);
            } else {
                System.out.println("错误：商品价格为空");
                order.setTotalPrice(new BigDecimal("0"));
            }
        } else {
            System.out.println("错误：无法获取商品价格");
            order.setTotalPrice(new BigDecimal("0"));
        }

        // 保存订单（这里简化处理，实际应该保存到数据库）
        // TODO: 调用订单服务保存到数据库

        return order;
    }

    /**
     * 健康检查接口
     */
    @GetMapping("/health")
    public Map<String, Object> health() {
        Map<String, Object> health = new HashMap<>();
        health.put("status", "UP"); // UP表示健康，DOWN表示不健康
        health.put("service", "service-order");
        health.put("serverPort", serverPort);
        health.put("timestamp", System.currentTimeMillis());

        return health;
    }

    //============================以下是服务配置============================//

    // 使用配置类管理Nacos配置
    @Autowired
    private AppProperties appProperties;

    @Autowired
    private OrderProperties orderProperties;

    @Autowired
    private RateLimitProperties rateLimitProperties;

    @GetMapping("/config-info")
    public Map<String, Object> getConfigInfo() {
        Map<String, Object> configInfo = new HashMap<>();

        // 从配置类获取配置
        configInfo.put("appName", appProperties.getName());
        configInfo.put("appVersion", appProperties.getVersion());
        configInfo.put("orderTimeout", orderProperties.getTimeout());
        configInfo.put("orderRetryMax", orderProperties.getRetryMax());
        configInfo.put("orderSwitchEnabled", orderProperties.getSwitchEnabled());
        configInfo.put("rateLimitQps", rateLimitProperties.getQps());
        configInfo.put("rateLimitEnabled", rateLimitProperties.getEnabled());
        configInfo.put("timestamp", System.currentTimeMillis());

        return configInfo;
    }

}
